package com.wjb.service;

import com.wjb.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * redis实现库存扣减配置（保证幂等性）
 * @author : 王济彬
 * @date: 2025/5/29 - 05 - 29 - 16:10
 * @Description: com.wjb.service
 * @version: 1.0
 */
@Service
public class StockService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedisCache redisCache;

    // 库存 key 前缀
    private static final String STOCK_KEY = "stock:";
    // 幂等性 key 前缀
    private static final String IDEMPOTENCY_KEY = "idempotency:";
    // 幂等性有效期（秒）
    private static final long IDEMPOTENCY_EXPIRE = 60 * 60; // 1小时

    // 带幂等性的库存扣减
    public boolean deductStock(int productId, int count, String deduplicationId) {
        String stockKey = STOCK_KEY + productId;
        String idempotencyKey = IDEMPOTENCY_KEY + deduplicationId;

        //进行幂等性检验
        Boolean exists = redisTemplate.opsForValue().setIfAbsent(
                idempotencyKey,   //幂等性校验字段
                "processing",     //键对应的值，标记请求正在处理
                IDEMPOTENCY_EXPIRE,   //过期时间（防止过长时间占用）
                TimeUnit.SECONDS);    //时间单位（秒）

        if (!exists) {
            return true;
        }
        System.out.println("尝试扣减");
        try {
              //lua脚本执行扣减库存
//            DefaultRedisScript<Long> script = new DefaultRedisScript<>(
//                    "local stock = redis.call('get', KEYS[1])\n" +
//                            "stock = tonumber(stock) or 0\n" +
//                            "local count = tonumber(ARGV[1])\n" +
//                            "if not count or count <= 0 then\n" +
//                            "   return -1\n" +
//                            "end\n" +
//                            "if stock >= count then\n" +
//                            "   redis.call('decrby', KEYS[1], count)\n" +
//                            "   return 1\n" +
//                            "else\n" +
//                            "   return 0\n" +
//                            "end",
//                    Long.class
//            );


//            Long result = redisTemplate.execute(script, Collections.singletonList(stockKey), String.valueOf(count));
//            return result != null && result == 1;

            // 获取原始库存值
            Object cacheObj = redisCache.getCacheObject("product");

            if (cacheObj == null) {
                // 处理 key 不存在的情况，例如初始化库存
                redisCache.setCacheObject("product", 100); // 假设初始库存为 100
                System.out.println("商品不存在，无法扣减");

                return false;
            }

            int stock;
            if (cacheObj instanceof Number) {
                stock = ((Number) cacheObj).intValue();
            } else if (cacheObj instanceof String) {
                try {
                    stock = Integer.parseInt((String) cacheObj);
                } catch (NumberFormatException e) {
                    throw new RuntimeException("缓存中的 product 不是合法的整数", e);
                }
            } else {
                throw new IllegalArgumentException("product 缓存类型不支持: " + cacheObj.getClass());
            }

            // 扣减库存
            stock -= 1;

            // 设置回 Redis
            redisCache.setCacheObject("product", stock);
            System.out.println("库存已更新：" + stock);
            return true;
        } finally {
            redisTemplate.opsForValue().set(idempotencyKey, "completed", IDEMPOTENCY_EXPIRE, TimeUnit.SECONDS);
        }
    }


    // 库存回滚（带幂等性）
    public void rollbackStock(int productId, int count, String deduplicationId) {
        String stockKey = STOCK_KEY + productId;
        String idempotencyKey = IDEMPOTENCY_KEY + deduplicationId;

        // 检查是否已回滚
        Boolean exists = redisTemplate.opsForValue().setIfAbsent(
                idempotencyKey, "processed", 60 * 60, TimeUnit.SECONDS);
        if (!exists) {
            // 执行库存回滚
            redisTemplate.opsForValue().increment(stockKey, count);
        }
    }
}